package livechat;

import java.io.IOException;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import javax.servlet.http.*;

import util.ServerToClient;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gson.Gson;

@SuppressWarnings("serial")
public class ChannelChatServlet extends HttpServlet{
	
	
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws IOException {
		req.setCharacterEncoding("UTF-8");
		resp.setContentType("text/html;charset=UTF-8");
		
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		
		if (user != null) {
			String sAction = req.getParameter("action");
			if(sAction.compareTo("get_token") == 0){
				String sToken = getTokenFromDataStore(user.getNickname(), false);
				Hashtable<String, String> hObjectReturn = new Hashtable<String, String>();
				hObjectReturn.put("token", sToken);
				Gson gson = new Gson();            	
				String json = gson.toJson(hObjectReturn);
				resp.getWriter().println(json);	
			}
			else if(sAction.compareTo("get_old_message") == 0){
				long lTime = Long.parseLong(req.getParameter("old_time"));
				if(lTime == 0)
				{
					Hashtable hObjectReturn = new Hashtable();
					hObjectReturn.put("old_time", new Date().getTime());
					Gson gson = new Gson();            	
					String json = gson.toJson(hObjectReturn);
					resp.getWriter().println(json);	
				}
				else
				{
					Vector<ChatLog> aChatLog = new Vector<ChatLog>();
					Query query = new Query("chatlog");
			        query.addFilter("time", Query.FilterOperator.LESS_THAN, lTime);
			        query.addSort("time", Query.SortDirection.DESCENDING);
			        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			        List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
			        for (Entity eChatLog : results) {
			        	lTime = Long.parseLong(eChatLog.getProperty("time").toString());
			        	ChatLog chat = new ChatLog(eChatLog.getProperty("username").toString(), eChatLog.getProperty("message").toString(), lTime);
			        	//chatlog.getProperty("username");
			        	aChatLog.add(chat);
					}
			        Hashtable hObjectReturn = new Hashtable();
					hObjectReturn.put("old_time", lTime);
					hObjectReturn.put("old_message", aChatLog);
					Gson gson = new Gson();            	
					String json = gson.toJson(hObjectReturn);
					resp.getWriter().println(json);	
				}
			}
			else if(sAction.compareTo("create_token") == 0){
				String sToken = getTokenFromDataStore(user.getNickname(), true);
				Hashtable<String, String> hObjectReturn = new Hashtable<String, String>();
				hObjectReturn.put("token", sToken);
				Gson gson = new Gson();            	
				String json = gson.toJson(hObjectReturn);
				resp.getWriter().println(json);	
			}
			else if(sAction.compareTo("send_message") == 0){
				String sMessage = req.getParameter("message");
				receiveMessage(user.getNickname(), sMessage);
			}
			else if(sAction.compareTo("join") == 0)
			{
				MemcacheService syncCache = MemcacheServiceFactory.getMemcacheService();
				Vector<String> vUsers = (Vector<String>) syncCache.get("room1");
				if(vUsers == null)
				{
					vUsers = new Vector<String>();
				}
				if(vUsers.indexOf(user.getNickname()) == -1)
				{
					vUsers.add(user.getNickname());
					syncCache.put("room1", vUsers);
					
					receiveMessage(user.getNickname(), "joined");
					
					Hashtable hNewUser = new Hashtable();
					hNewUser.put("all_user", vUsers);
					ServerToClient.sendMessageToAllUsers(ServerToClient.NEW_USER_JOIN, hNewUser, "");
				}
			}
			else if(sAction.compareTo("send_board_path") == 0)
			{
				String sEmail = req.getParameter("email");
				String sAllPos = req.getParameter("all_pos");
				
				Hashtable hNewPaths = new Hashtable();
				hNewPaths.put("all_pos", sAllPos);
				ServerToClient.sendMessageToAllUsers(ServerToClient.NEW_BOARD_PATH, hNewPaths, sEmail);
			}
		}
    }
	
	private String getTokenFromDataStore(String sUsername, Boolean bForceNew)
	{
		
		if(bForceNew == true)
			return createNewTokenForUser(sUsername);
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		try {
			Key kUserkey = KeyFactory.createKey("PersonToken", sUsername);
			Entity user_token = datastore.get(kUserkey);
			if((Long) user_token.getProperty("time") < (new Date().getTime() - (24*60-1)*1000))
			{
				return createNewTokenForUser(sUsername);
			}
			else
				return (String)user_token.getProperty("token");
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			return createNewTokenForUser(sUsername);
		}
	}
	
	
	private String createNewTokenForUser(String sUsername)
	{
		Key kUserkey = KeyFactory.createKey("PersonToken", sUsername);
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		ChannelService channelService = ChannelServiceFactory.getChannelService();
		String token = channelService.createChannel(getChannelKey(sUsername), 24*60-1);
		Entity user_token = new Entity(kUserkey);
		user_token.setProperty("token", token);
		user_token.setProperty("time", new Date().getTime());
		datastore.put(user_token);
		return token;
	}
	
	private String getChannelKey(String sUsername)
	{
		return "channelchat_" + sUsername;
	}
	
	private void receiveMessage(String sUsername, String sMessage)
	{
        if (sMessage != null) {
        	DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        	ChatLog chat = new ChatLog(sUsername, sMessage, new Date().getTime());
        	Entity chatlog = new Entity("chatlog");
        	chatlog.setProperty("username", chat.get_sUserName());
        	chatlog.setProperty("message", chat.get_sMessage());
        	chatlog.setProperty("time", chat.get_lTime());
        	datastore.put(chatlog);	    
        	
        	ServerToClient.sendMessageToAllUsers(ServerToClient.NEW_MESSAGE, chat, "");
        }		
	}
	
	
}
